#ifndef __LOG_FLASH_H__
#define __LOG_FLASH_H__

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>

//#define LOG_FLASH_USING_HOOK	
//#define USE_FLASH_ERASE			

#define SYSTEM_LOG_MAGIC_PARAM		(0x87654321)
#define TIME_PREFIX_SIZE			(25)						/* log data inf*/
#define PRINT_MAX_SIZE				(1024 + TIME_PREFIX_SIZE)	/*  */
#define LOG_FLASH_SECTOR_SIZE		(4 * 1024)

typedef enum{
    FLASH_CATALOG_ZONE = 0,	/* 系统目录 */
    FLASH_SYSLOG_PARA_ZONE, /* 系统参数 */
    FLASH_SYSLOG_ZONE,		/* 日志  */
    FLASH_ZONEX,
}flash_zone_e;

typedef struct{
	uint32_t start_address; /* 起始地址 */
    uint32_t end_address;	/* 结束地址 */
    flash_zone_e zone;		/* 分区 */
}flash_table_t;

/* 日志分区表 */
static const flash_table_t flash_table[] = {
	{ .zone = FLASH_CATALOG_ZONE,       .start_address = 0x00000000, .end_address = 0x000000a0},  //min:0x14
	{ .zone = FLASH_SYSLOG_PARA_ZONE,   .start_address = 0x00001000, .end_address = 0x00001060},  //min:0x60
	{ .zone = FLASH_SYSLOG_ZONE,        .start_address = 0x00002000, .end_address = 0x00002fff},  //min:PRINT_MAX_SIZE
};

typedef struct {
	uint32_t magic;			/* 幻数 */
	uint16_t crc;			/* crc校验 */
	uint16_t len;			/* 长度 */
} single_sav_t;

#define DayToSecond 		86400   
#define HourToSecond 		3600    
#define MinuteToSecond		60      
#define LeapYear			366     
#define CommonYear			365     
#define LeapFeb             29      
#define CommonFeb           28		
typedef struct {
	uint16_t 	Year;		
	uint8_t		Month;		
	uint8_t		Day;		
	uint8_t     Hour;		
	uint8_t     Minute;		
	uint8_t 	Second;		
	uint16_t 	Ms;			
}flash_time_t;   

typedef struct {
	uint32_t   write_pos; 	          	/* 写位置 记录每次写日志时写入的起始地址，在这之前都是已经写入的数据*/
	uint32_t   catalog_num;	          	/* 目录项个数 */
	uint8_t    log_cyclic_status;	  	/* 系统日志环形写状态 意思是当系统日志区写满后，要回到起始位置继续写入数据*/
	uint8_t    catalog_cyclic_status; 	/* 系统日志环形写状态 意思是当目录区写满后，要回到起始位置继续写入数据*/
	flash_time_t     log_current_time; 	/* 存储最新时间 */
}system_log_t;

typedef struct {
	uint32_t log_id; 	  		/* 日志ID */
	uint32_t log_addr;    		/* 日志地址 */
	uint32_t log_offset;  		/* 日志写入的起始地址 */
	flash_time_t   log_time;	/* 目录存储的时间 */
}system_catalog_t;

typedef struct {
	single_sav_t crc_val;			/* 存储日志的幻数、CRC */
	system_log_t system_log;		/* 系统日志 */
	system_catalog_t system_catalog;/* 当前系统目录信息 */
}sys_log_param_t;

typedef struct {
	uint8_t system_print_level;	     /* 系统打印等级 */
	uint8_t system_log_print_enable; /* 系统打印使能 */
	uint32_t system_log_print_id;    /* 系统当前目录ID */
	uint32_t system_log_param_addr;  /* 系统日志参数地址 */
} sys_ram_t;

typedef struct {	
	int level;						 /* 等级  */
	char *fmt_str;                   /* 标头 */
}system_print_fmt_t;

typedef struct
{
	uint16_t (*log_flash_crc16)(uint8_t* puchMsg, uint16_t usDataLen);
	int (*log_flash_write)(uint8_t * _pBuf, uint32_t _uiWriteAddr, uint16_t _usSize);
	int (*log_flash_read)(uint8_t * _pBuf, uint32_t _uiReadAddr, uint32_t _uiSize);
	int (*log_flash_erase)(uint32_t erase_addr);
	int (*log_flash_time)(flash_time_t *date);
	uint32_t (*log_flash_lock)(void);
	uint32_t (*log_flash_unlock)(uint32_t level);
}log_flash_ops_def;

#define ALL_LOG_PRINT				0xffffffff 	 
#define LOG_CLOSE_LEVEL				0x00 
#define LOG_ERROR_LEVEL				0x01 
#define LOG_WARN_LEVEL				0x02 
#define LOG_INFO_LEVEL				0x03 
#define LOG_DEBUG_LEVEL				0x04 
#define LOG_RECORD_LEVEL			0x10 

int slog_format(uint8_t level, const char *fmt, ...);
#define log_flash_debug(fmt, args...)		slog_format(LOG_DEBUG_LEVEL, fmt, ##args)
#define log_flash_info(fmt, args...)		slog_format(LOG_INFO_LEVEL, fmt, ##args)
#define log_flash_warn(fmt, args...)		slog_format(LOG_WARN_LEVEL, fmt, ##args)
#define log_flash_error(fmt, args...)		slog_format(LOG_ERROR_LEVEL, fmt, ##args)
#define log_flash_record(fmt, args...)		slog_format(LOG_RECORD_LEVEL, fmt, ##args)
#define log_flash_print(...)				printf(__VA_ARGS__)		


int log_flash_register( uint16_t (*log_flash_crc16)(uint8_t* puchMsg, uint16_t usDataLen),
						int (*log_flash_write)(uint8_t * _pBuf, uint32_t _uiWriteAddr, uint16_t _usSize),
						int (*log_flash_read)(uint8_t * _pBuf, uint32_t _uiReadAddr, uint32_t _uiSize),
						int (*log_flash_erase)(uint32_t erase_addr),
						int (*log_flash_time)(flash_time_t *date),
						uint32_t (*log_flash_lock)(void),
						uint32_t (*log_flash_unlock)(uint32_t level) );
int system_log_task(uint32_t argc, char **argv);
int log_flash_erase_all(void);
flash_time_t* log_flash_MsToTime(uint32_t s_ms);
#ifdef LOG_FLASH_USING_HOOK
void log_flash_inited_sethook(void (*hook)(void* user_data));
#endif /* defined(LOG_FLASH_USING_HOOK) */
#endif
